package panda.index.bplustree;

import panda.file.Block;
import panda.query.struct.*;
import panda.record.*;
import panda.transaction.*;

public class TreeDir {
	private TreePage content;
	private String filename;
	private TableToken tbl;
	private Transaction tx;

	TreeDir(Block blk, TableToken tt, Transaction t) {
		tx = t;
		tbl = tt;
		content = new TreePage(blk, tbl, tx);
		filename = blk.getFileName();
	}

	public int search(Constant searchkey) {
		Block childblk = findChildBlock(searchkey);
		//System.out.println("recordNum == " + content.getRecordNum());

		while (content.getLevel() > 0) {
			//System.out.println("level -- " + content.getLevel());
			content.close();
			content = new TreePage(childblk, tbl, tx);
			childblk = findChildBlock(searchkey);
		}

		return childblk.getBlockNumber();
	}
	
	public int searchSmallestRecord() {
		if (content.getLevel() == 0) {
			return content.getChildBlockNum(0);
		}
		
		Block childblk = null;
		
		while (content.getLevel() > 0) {
		    Constant smallest = content.getData(0);
		    childblk = findChildBlock(smallest);
		    content.close();
		    content = new TreePage(childblk, tbl, tx);
	    }
		
		return childblk.getBlockNumber();
	}

	// TODO
	public void createNewRoot(DirEntry de) {
		Constant firstData = content.getData(0);
		int level = content.getLevel();
		Block newblk = content.split(0, level);
		//Block newblk = content.append(level);
		//content.moveTo(newblk);
		
		DirEntry oldroot = new DirEntry(firstData, newblk.getBlockNumber());
		insertEntry(oldroot);
		insertEntry(de);
		content.setLevel(level + 1);
		System.out.println("lllllllleeeeeeeeeevvvvvvvvvvveeeeeeeeeeellllll " + (level + 1));
	}
    
	/*
	 * recursive implementation of findInsertBlock
	 */
	public DirEntry findInsertBlock(DirEntry de) {
		if (content.getLevel() == 0) {
			return insertEntry(de);
		}

		Block childblk = findChildBlock(de.getData());
		TreeDir childDir = new TreeDir(childblk, tbl, tx);
		DirEntry entry = childDir.findInsertBlock(de);
        childDir.close();
        
		if (entry == null) {
			return null;
		} else {
			return insertEntry(entry);
		}
	}

	// TODO
	public DirEntry insertEntry(DirEntry de) {
		//System.out.println("insertEntry ----- " + (de.data).getContentValue());
		int slot = 1 + content.findSlotBefore(de.data);
		//System.out.println("slot ----------------------------- " + slot);
		content.insertDir(slot, de.getData(), de.getBlockNum());
		
		if (!content.isFull()) {
			return null;
		}
		
		int level = content.getLevel();
		int splitpos = content.getRecordNum() / 2;
		Constant val = content.getData(splitpos);
		
		Block blk = content.split(splitpos, level);
	
		return (new DirEntry(val, blk.getBlockNumber()));
	}

	public Block findChildBlock(Constant searchkey) {
		//int slot = content.findSlotBefore(searchkey);
		int slot = content.findSlotBefore2(searchkey);
		//System.out.println("1 ----------- " + slot);
		//System.out.println("2 ----------- " + slot2);
		/*if (slot != slot2) {
			System.out.println("11111111111111111111111111111111111111111111111111");
		}*/
		
		if (content.getData(slot + 1).compareTo(searchkey) == 0) {
			slot++;
		}
		
		int blknum = content.getChildBlockNum(slot);
		
		//if (level == 0) return new Block("leaf1.bt", blknum);
		return new Block(filename, blknum);
	}
	
	public void close() {
		content.close();
	}
}